﻿
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
 

namespace HBase {
    /**
   *┌────────────────────────────────────────────────┐
   *│　描    述：Fade                                                    
   *│　作    者：sgj                                              
   *│　版    本：1.0                                              
   *│　创建时间：2020/10/19 12:58:20                        
   *└────────────────────────────────────────────────┘
   **/
    public class HttpApiFacade {
        static Dictionary<String ,List<HttpMethod>> classDictionary = new Dictionary<String ,List<HttpMethod>>();

        public static bool httpServerLog = false;
        static public HttpParam getAction(String path) {
            int index = path.Substring(1).IndexOf("/");
            String classNameUrl = null;
            if( index == -1 ) {
                classNameUrl = path;
            } else {
                classNameUrl = path.Substring(0 ,index + 1);
            }
            classNameUrl = classNameUrl.ToLower();
            HttpParam p = selectParam(path ,classNameUrl);
            if( p == null ) {
                p = selectParam(path ,"/");
            }
            return p;
        }
        static HttpParam selectParam(String path ,String root) {
            if( !classDictionary.ContainsKey(root) ) {
                return null;
            }
            List<HttpMethod> mathDictionary = classDictionary[root];
            foreach( HttpMethod item in mathDictionary ) {
                if( Regex.IsMatch(path ,item.path ,RegexOptions.IgnoreCase) ) {
                    Match mc = Regex.Match(path ,item.path ,RegexOptions.Multiline | RegexOptions.IgnoreCase);
                    GroupCollection mg = mc.Groups;
                    Dictionary<String ,object> paramDict = new Dictionary<string ,object>();
                    for( int i = 0;i < mg.Count - 1;i++ ) {

                        var value = mg[i + 1];
                        List<String> uriParamKey = item.uriParamKey;
                        if( i < uriParamKey.Count ) {
                            String param = value.ToString();
                            if( !String.IsNullOrEmpty(param) && param.Length > 1 ) {
                                paramDict.Add(uriParamKey[i] ,param.Substring(1));
                            } else {
                                paramDict.Add(uriParamKey[i] ,"");
                            }

                        }
                    }
                    return new HttpParam() { mc = paramDict ,meth = item };
                }
            }
            return null;
        }
        static public void initTypes(int tokenTime  ,bool httpServerLog) {
            HttpApiFacade.httpServerLog = httpServerLog;
            CookieHelper.tokenTime = tokenTime;
            if( classDictionary.Count != 0 ) {
                return;
            }
            loadAll();
            Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
            for( int i=0;i<ass.Length;i++ ) {
                Assembly asm = ass[i];
                AssemblyName name = asm.GetName();
                AssemblyCompanyAttribute attr = ( AssemblyCompanyAttribute ) asm.GetCustomAttribute(typeof(AssemblyCompanyAttribute));
                if( attr == null || attr.Company.IndexOf("hhhqyhjf") == -1 ) {
                    continue;
                }

                try {
                    Type[] ts = asm.GetTypes();
                    foreach( var t in ts ) {
                        addHttpMethod(t);
                    }
                } catch( Exception e ) {
                    LoggerCommon.errorFile(name + "upload  error", e);
                    
                }

            }

            new HttpServer();
        }

        private static void loadAll() {

            AppDomain domain = AppDomain.CurrentDomain;
            String baseDir = domain.BaseDirectory;
            DirectoryInfo root = new DirectoryInfo(baseDir);
            FileInfo[] files = root.GetFiles();

            foreach( FileInfo finfo in files ) {
                String name = finfo.FullName;
                loadFile(name);
            }
        }

        private static void loadFile(String name) {
            if( !name.EndsWith("dll") ) {
                return;
            }
            Assembly[] ass1 = AppDomain.CurrentDomain.GetAssemblies();
            foreach( Assembly ass in ass1 ) {
                if( ass.Location == name ) {
                    return;
                }
            }
            try {
                Assembly.LoadFrom(name);
            } catch {
            }



        }
        static void addHttpMethod(Type t) {
            if( !t.IsClass ) {
                return;
            }
            if( !t.IsSubclassOf(typeof(BaseApiController)) ) {
                return;
            }

            RoutePrefixAttribute a = ( RoutePrefixAttribute ) Attribute.GetCustomAttribute(t ,typeof(RoutePrefixAttribute));
            AuthorizationFilterAttribute authorization = ( AuthorizationFilterAttribute ) Attribute.GetCustomAttribute(t ,typeof(AuthorizationFilterAttribute));

            String basePath = "";
            String key = "";
            if( a != null ) {
                basePath = a.Prefix;
                int index = basePath.IndexOf("/");
                if( index == -1 ) {
                    key = "/" + basePath;
                } else {
                    key = "/" + basePath.Substring(0 ,index);
                }
                basePath = "/" + basePath;
            } else {
                basePath = "";
                key = "/";
            }

            if( !classDictionary.ContainsKey(key.ToLower()) ) {
                classDictionary.Add(key.ToLower() ,new List<HttpMethod>());
            }
            Object server = ( Object ) Activator.CreateInstance(t);
            MethodInfo[] mis = t.GetMethods();
            foreach( MethodInfo mi in mis ) {
                RouteAttribute b = ( RouteAttribute ) Attribute.GetCustomAttribute(mi ,typeof(RouteAttribute));
                if( b == null ) {
                    continue;
                }
                String uri = basePath + "/" + b.Template;
                classDictionary[key.ToLower()].Add(new HttpMethod(uri ,server ,mi ,authorization != null));
            }
        }
    }
    public class HttpParam {
        public Dictionary<String ,object> mc;//实际参数
        Object getValue(String key) {
            if( mc.ContainsKey(key) ) {
                return mc[key];
            } else {
                return null;
            }
        }
        public HttpMethod meth;
        public Object doAction() {

            int len = meth.parameterInfos.Length;
            Object[] param = new Object[len];
            for( int i = 0;i < len;i++ ) {
                ParameterInfo pi = meth.parameterInfos[i];
                String key = pi.Name.ToString();
                if( pi.ParameterType == typeof(long) ) {

                    param[i] = Convert.ToInt64(getValue(key));
                } else if( pi.ParameterType == typeof(int) ) {
                    param[i] = Convert.ToInt32(getValue(key));
                } else {
                    param[i] = getValue(key);
                }
            }
            return meth.method.Invoke(meth.server ,param);//执行
        }
    }
    public class HttpMethod {
        public String path;
        public bool authorization;
        public ControlName controlName;
        public Object server;
        public MethodInfo method;
        public ParameterInfo[] parameterInfos;
        public ParameterInfo body;
        public List<String> uriParamKey = new List<string>();
        public HttpMethod(String path1 ,Object server ,MethodInfo meth ,bool authorization) {
            this.path = path1;
            this.method = meth;
            this.server = server;
            this.authorization = authorization;


            controlName = ( ControlName ) Attribute.GetCustomAttribute(method ,typeof(ControlName));
            MatchCollection mc = Regex.Matches(path ,@"/\{\w+\??\}");
            foreach( var key in mc ) {
                String v = key.ToString();
                int length = v.Length - 2;
                if( v.IndexOf("?") == -1 ) {
                    length -= 1;
                } else {
                    length -= 2;
                }

                uriParamKey.Add(v.Substring(2 ,length));
                path = path.Replace(v ,@"(/[\w!-.0-`]*)?");
            }
            this.path = "^" + this.path + "$";

            //LoggerCommon.consol("init:" + path);
            parameterInfos = method.GetParameters();
            foreach( ParameterInfo info in parameterInfos ) {

                FromBodyAttribute b = ( FromBodyAttribute ) Attribute.GetCustomAttribute(info ,typeof(FromBodyAttribute));
                Type type = info.ParameterType;
                if( type != typeof(String) && type.IsClass ) {
                    if( body != null ) {
                        throw new Exception("参数异常");
                    }
                    body = info;
                }
            }
        }
    }
}
